package com.cloudshop.service.common.aspect;

import com.alibaba.fastjson.JSONObject;
import com.cloudshop.service.common.dto.RestControllerResult;
import com.cloudshop.service.common.exception.LoginException;
import com.cloudshop.service.common.log.LogManager;
import com.cloudshop.service.common.utils.CheckEmptyUtil;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

/**
 * Controller层切面.
 *
 * @author 宫新程
 * @since 2019/3/29 21:47
 */
@Slf4j
@Aspect
@Component
public class LogMvcAspect {

  /** 微服务Controller层的所有方法. */
  @Pointcut("execution(* com.cloudshop.service..controller..*(..))")
  public void restControllerMethods() {}

  /**
   * Controller层的所有方法环绕通知.
   *
   * @param joinPoint 连接点.
   * @return Object
   * @throws Throwable 异常
   */
  @Around("restControllerMethods()")
  public Object restAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    // 类名
    String className = joinPoint.getTarget().getClass().getName();
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    // 方法名
    Method method = signature.getMethod();
    String methodName = method.getName();
    // 参数名称
    String[] parameterNames = signature.getParameterNames();
    // 参数值
    Object[] args = joinPoint.getArgs();

    // 将如入参名称和入参值匹配，并转成json串.
    Map<String, Object> paramMap = new HashMap<>();
    if (CheckEmptyUtil.isNotEmpty(parameterNames)) {
      for (int i = 0; i < parameterNames.length; i++) {
        Object arg = args[i];
        if (arg instanceof ServletRequest
            || arg instanceof HttpSession
            || arg instanceof ServletResponse
            || arg instanceof MultipartFile) {
          continue;
        }
        // 去除敏感属性.
        if ("password".equals(parameterNames[i])) {
          continue;
        }
        paramMap.put(parameterNames[i], arg);
      }
    }
    String methodParams = JSONObject.toJSONString(paramMap);
    try {
      // 设置参数信息.
      LogManager.aspectInit(className, methodName, methodParams);
      Object proceed = joinPoint.proceed();
      LogManager.setHttpStatus(200);
      return proceed;
    } catch (LoginException e) {
      LogManager.setHttpStatus(500);
      LogManager.setException(e.getMessage());
      RestControllerResult<String> result = new RestControllerResult<>();
      result.setErrorMsg(e.getMessage());
      result.setSuccess(false);
      return result;
    } catch (Exception e) {
      e.printStackTrace();
      LogManager.setException(e.getMessage());
      LogManager.setHttpStatus(500);
      RestControllerResult<String> result = new RestControllerResult<>();
      result.setSuccess(false);
      result.setErrorMsg(e.getMessage());
      return result;
    } finally {
      // 设置Controller处理时间
      LogManager.setConsume(System.currentTimeMillis() - start);
      log.info("Has Get All Controller Params :" + this.getClass().getName());
    }
  }
}
